﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace Falafel.Controls.Dialogs
{
    public enum DialogBaseButton
    {
        Ok,
        OkCancel,
        YesNo
    }

    public enum DialogBaseType
    {
        Information,
        Warning,
        Error
    }
    
    public class DialogBase : ChildWindow
    {
        private StackPanel _buttonStackPanel;
        protected StackPanel ButtonStackPanel
        {
            get
            {
                if (_buttonStackPanel == null)
                {
                    FrameworkElement grid = (FrameworkElement)FindName("LayoutRoot");
                    List<StackPanel> panels = grid.GetDescendants<StackPanel>();

                    _buttonStackPanel = panels.Where(sp => sp.Name == "StackPanelButtons").First();
                }

                return _buttonStackPanel;
            }
        }

        private Image _alertImage;
        protected Image AlertImage
        {
            get
            {
                if (_alertImage == null)
                {
                    FrameworkElement grid = (FrameworkElement)FindName("LayoutRoot");
                    List<Image> images = grid.GetDescendants<Image>();

                    _alertImage = images.Where(i => i.Name == "ImageAlertType").First();
                }

                return _alertImage;
            }
        }

        public object UserState { get; protected set; }

        private static readonly string AssemblyName = Assembly.GetCallingAssembly().FullName.Substring(0, Assembly. GetCallingAssembly().FullName.IndexOf(','));
        protected static readonly Thickness FirstButtonOnRightThickness = new Thickness(0, 12, 3, 0);
        protected static readonly Thickness SecondButtonOnRightThickness = new Thickness(0, 12, 0, 0);
        protected static readonly Uri InformationImageUri = new Uri(@"/" + AssemblyName + ";component/Images/information-icon.png", UriKind.Relative);
        protected static readonly Uri WarningImageUri = new Uri(@"/" + AssemblyName + ";component/Images/warning-icon.png", UriKind.Relative);
        protected static readonly Uri ErrorImageUri = new Uri(@"/" + AssemblyName + ";component/Images/error-icon.png", UriKind.Relative);

        protected DialogBaseButton BottomButtons;

        protected void Init(string title, DialogBaseButton dialogBaseButton, DialogBaseType dialogBaseType, object userInfo)
        {
            UserState = userInfo;

            SetTitle(title);
            SetAlert(dialogBaseType);
            SetButtons(dialogBaseButton);
        }

        protected void SetAlert(DialogBaseType dialogBaseType)
        {
            switch (dialogBaseType)
            {
                case DialogBaseType.Information:
                    AlertImage.Source = new BitmapImage(InformationImageUri);
                    break;
                case DialogBaseType.Warning:
                    AlertImage.Source = new BitmapImage(WarningImageUri);
                    break;
                case DialogBaseType.Error:
                    AlertImage.Source = new BitmapImage(ErrorImageUri);
                    break;
                default:
                    throw new InvalidOperationException("Invalid alert type");
            }
        }

        public void SetButtons(DialogBaseButton dialogBaseButton)
        {
            BottomButtons = dialogBaseButton;
        }

        public void SetTitle(string title)
        {
            Title = title;
        }

        public new void Show()
        {
            base.Show();
        }

        protected void LayoutButtons()
        {
            switch (BottomButtons)
            {
                case DialogBaseButton.Ok:
                    ButtonStackPanel.Children.Add(GetOkButton(FirstButtonOnRightThickness));
                    break;
                case DialogBaseButton.OkCancel:
                    ButtonStackPanel.Children.Add(GetOkButton(FirstButtonOnRightThickness));
                    ButtonStackPanel.Children.Add(GetCancelButton(SecondButtonOnRightThickness));
                    break;
                case DialogBaseButton.YesNo:
                    ButtonStackPanel.Children.Add(GetYesButton(FirstButtonOnRightThickness));
                    ButtonStackPanel.Children.Add(GetNoButton(SecondButtonOnRightThickness));
                    break;
            }
        }

        private void OKButton_Click(object sender, RoutedEventArgs e)
        {
            DialogResult = true;
        }

        private void CancelButton_Click(object sender, RoutedEventArgs e)
        {
            DialogResult = false;
        }

        private Button GetOkButton(Thickness buttonMargin)
        {
            Button aButton = new Button();
            aButton.Name = "OKButton";
            aButton.Content = "OK";
            SetButtonAttributes(aButton, buttonMargin);
            aButton.Click += OKButton_Click;

            return aButton;
        }

        private Button GetCancelButton(Thickness buttonMargin)
        {
            Button aButton = new Button();
            aButton.Name = "CancelButton";
            aButton.Content = "Cancel";
            SetButtonAttributes(aButton, buttonMargin);
            aButton.Click += CancelButton_Click;

            return aButton;
        }

        private Button GetYesButton(Thickness buttonMargin)
        {
            Button aButton = new Button();
            aButton.Name = "YesButton";
            aButton.Content = "Yes";
            SetButtonAttributes(aButton, buttonMargin);
            aButton.Click += OKButton_Click;

            return aButton;
        }

        private Button GetNoButton(Thickness buttonMargin)
        {
            Button aButton = new Button();
            aButton.Name = "NoButton";
            aButton.Content = "No";
            SetButtonAttributes(aButton, buttonMargin);
            aButton.Click += CancelButton_Click;

            return aButton;
        }

        protected static void SetButtonAttributes(Button aButton, Thickness buttonMargin)
        {
            aButton.Width = 75;
            aButton.Height = 23;
            aButton.HorizontalAlignment = HorizontalAlignment.Right;
            aButton.VerticalAlignment = VerticalAlignment.Bottom;
            aButton.Margin = buttonMargin;
        }
    }
}
